package com.xueqiu.movieplaymanagersystem.config;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.xueqiu.movieplaymanagersystem.utils.DateUtils;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import static com.xueqiu.movieplaymanagersystem.constant.configConstant.TOTAL_ATTRIBUTE_NAME;

/**
 * @author xueqiu
 */
public class VisitInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    /**
     * 拦截器方法，用于记录用户访问信息的，包括用户IP和访问次数
     * 注解@SuppressWarnings("unchecked")用于抑制编译器产生的“未经检查的转换”警告
     * (Set<String>) servletContext.getAttribute(currentWeek);
     * (Set<String>) servletContext.getAttribute("total");
     * 会产生“未经检查的转换”警告
     *
     * @param request  request
     * @param response response
     * @param handler  handler
     * @param ex       ex
     * @throws Exception Exception
     */
    @Override
    @SuppressWarnings("unchecked")
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //获取当前周的周数
        String currentWeek = DateUtils.weekOfYear();
        //获取ServletContext实例
        ServletContext servletContext = request.getServletContext();
        //从servletContext中获取当前周的访问信息集合attribute
        Set<String> attribute = (Set<String>) servletContext.getAttribute(currentWeek);
        //从servletContext中获取总的访问信息集合
        Set<String> total = (Set<String>) servletContext.getAttribute(TOTAL_ATTRIBUTE_NAME);
        //如果当前时间是星期1，那么清空当前周的访问信息
        if ("1".equals(DateUtils.weekOfMonth(new Date()))) {
            if (attribute != null) {
                attribute = null;
            }
        }
        //将当前请求的IP地址添加到当前周的`访问信息集合`中，之后将其保存至servletContext中
        setAttribute(
                //当前周的访问信息集合
                attribute,
                //请求的IP地址
                request,
                //保存至servletContext
                servletContext,
                //当前周的周数充当`访问信息集合的名称`
                currentWeek
        );
        //将当前请求的IP地址添加到`总的访问信息集合`中，之后将其保存至servletContext中
        setAttribute(
                //总的访问信息集合
                total,
                //请求的IP地址
                request,
                //保存至servletContext
                servletContext,
                //totalAttributeName充当`总的访问信息集合的名称`
                TOTAL_ATTRIBUTE_NAME
        );
    }

    /**
     * 将当前请求的IP地址添加到“总的”或“当前周的”访问信息集合中，之后将其保存至servletContext中
     *
     * @param attributeObject “总的”或“当前周的”访问信息集合
     * @param request         包含IP地址的请求
     * @param servletContext  servletContext
     * @param attributeName   访问信息集合的名称
     */
    private void setAttribute(
            Set<String> attributeObject,
            HttpServletRequest request,
            ServletContext servletContext,
            String attributeName
    ) {
        if (attributeObject == null) {
            attributeObject = new HashSet<>();
        }
        //添加IP地址到访问信息集合
        attributeObject.add(request.getRemoteAddr());
        //添加访问信息集合到servletContext
        servletContext.setAttribute(attributeName, attributeObject);
    }
}
